package descentFly.away3D4.chips
{
	import UIFree.ObjectEvent;
	
	import away3d.animators.data.AnimationBase;
	import away3d.containers.ObjectContainer3D;
	import away3d.materials.ColorMaterial;
	import away3d.materials.MaterialBase;
	import away3d.primitives.Sphere;
	import away3d.tools.utils.Ray;
	
	import descentFly.app.radar.df_radarEvent;
	import descentFly.away3D4.df_awaySpace;
	import descentFly.away3D4.df_awayUtils;
	import descentFly.away3D4.material.df_UVAnimMaterial;
	import descentFly.chips.df_chip;
	import descentFly.controller.FlyController;
	import descentFly.controller.df_userController;
	import descentFly.df_space;
	import descentFly.df_utils;
	import descentFly.jiglib.utils;
	import descentFly.weaponts.IAwayBullet;
	import descentFly.weaponts.IBullet;
	
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.geom.Matrix3D;
	import flash.geom.Vector3D;
	
	import jiglib.physics.RigidBody;
	import jiglib.plugin.away3d4.Away3D4Physics;
	
	import space.sp_utils;

	public class df_chipAway extends df_chip {
		public static const SETBODY: String 	= 'SETBODY';
		
		private var _body				: RigidBody;
		private var _angleVelocity		: Vector3D;
		private var _moveTo				: Number;
		private var _slideTo			: Number;
		private var _noActiveSphere		: Sphere;
		private var _noActiveSphereVis	: Boolean;
		private var _prev				: Vector3D;
		
		
		public function df_chipAway(a_space: df_space, a_options: Object) {
			super(a_space, a_options);
		}
		
		override protected function initialize(): void {
			_noActiveSphereVis	= false;
			_moveTo 			= 0;
			_slideTo			= 0;
			_angleVelocity 		= new Vector3D();
			initBody();
//			spaceAway.updateObjectFromEnv(awayObject);
			super.initialize();
		}
		
		override protected function listenEvents():void {
			super.listenEvents();
			addEventListener(df_userController.ACTION, doAction);
		}
		
		override protected function removeEvents():void {
			super.removeEvents();
			removeEventListener(df_userController.ACTION, doAction);
			if (spaceAway) spaceAway.view.stage.removeEventListener(df_radarEvent.GETPOINTS, doRadar);
		}
		
		protected function doRadar(e: df_radarEvent): void {
			if (body) {
				var myChip: df_chipAway = spaceAway.myChipAway;
				if (myChip && (myChip != this) && myChip.body) {
					var mat: Matrix3D = myChip.body.skin.transform.clone();
					mat.invert();
					var v: Vector3D = mat.transformVector(body.currentState.position);
					v.y = 0;
					var angle: Number = Vector3D.angleBetween(e.direct, v);
					if ((angle > 0) && (sp_utils.radiansToDegrees(angle) <= e.angle)) {
						e.addPoint(v, controller.typeFromRadar());
					}
				}
			}
		}
		
		protected function doAction(e: ObjectEvent): void {
			if (e.object.action == df_userController.ACTION_NOACTIVE) {
				noActiveSphere = e.object.state;
			}
		}
		
		protected function disposeActiveSphere(): void {
			if (_noActiveSphere) {
				_noActiveSphere.parent.removeChild(_noActiveSphere);
				_noActiveSphere.dispose(false);
				_noActiveSphere = null;
			}
		}
		
		override public function dispose():void {
			disposeActiveSphere();
			if (awayObject) awayObject.dispose(false);
			if (body) this.spaceAway.physic.removeBody(body);
			super.dispose();
		}
		
		protected function get awayObject(): ObjectContainer3D {
			return null;
		}
		
		public function actorForEach(func: Function): Object {
			if (spaceAway.myChip)
				return func(spaceAway.myChip as df_chipAway);
			return null;
		}
		
		protected function get physic():Away3D4Physics {
			return spaceAway.physic;
		}
		
		protected function initBody(): void {
			setBody(options.body);
		}
		
		protected function get spaceAway(): df_awaySpace {
			return this.space as df_awaySpace;
		}
		
		protected function setBody(a_body: RigidBody): void {
			_body = a_body;
			if (a_body) {
				var v: Vector3D;
				if (options.orientation) {
					if (options.orientation as Matrix3D)
						_body.setOrientation(options.orientation as Matrix3D);
					else {
						v = utils.asVector(options.orientation);
						_body.rotationX = v.x;
						_body.rotationY = v.y;
						_body.rotationZ = v.z;
					}
				}
				if (options.position) {
					v = utils.asVector(options.position);
					_body.x = v.x;
					_body.y = v.y;
					_body.z = v.z;
				}
				
				disposeActiveSphere();
				
				spaceAway.view.stage.addEventListener(df_radarEvent.GETPOINTS, doRadar);
			}
			setEnableBody(_body != null);
			
			dispatchEvent(new Event(SETBODY));
		}
		
		protected function addBodyInPhysic(a_box: RigidBody): void {
			spaceAway.physic.addBody(a_box);
		}
		
		protected function createNoactiveSphere(): void {
			df_awayUtils.createMaterial(options.noActiveMaterial, function(material: MaterialBase): void {
				
				var sphere: Sphere = new Sphere(material, attackableRadius * 1.4);
				if (material is df_UVAnimMaterial)
					(material as df_UVAnimMaterial).beginAnimation(sphere.subMeshes[0]);
				setNoActiveSphere(sphere);
				
			}, function(): MaterialBase {
				return new ColorMaterial(0xFFFFFF, 0.2);
			});
//			setNoActiveSphere(new df_noActiveSphere(new ColorMaterial(0xFFFFFF, 0.3), attackableRadius * 1.4))
		}
		
		protected function setNoActiveSphere(a_value: Sphere): void {
			_noActiveSphere 			= a_value;
			_noActiveSphere.transform 	= _body.skin.transform;
			_noActiveSphere.visible		= _noActiveSphereVis;
			
			spaceAway.view.view.scene.addChild(_noActiveSphere);
		}
		
		public function get noActiveSphere(): Boolean {
			return _noActiveSphereVis;
		}
		
		public function set noActiveSphere(a_set: Boolean): void {
			if (noActiveSphere != a_set) {
				_noActiveSphereVis = a_set;
				
				if (_noActiveSphereVis && body) {
					if (!_noActiveSphere) createNoactiveSphere();
				}
				
				if (_noActiveSphere) _noActiveSphere.visible = _noActiveSphereVis;
				if (body) body.movable = !_noActiveSphereVis;
			}
		}
		
		public function setEnableBody(enable: Boolean): Boolean {
			if (enable) addBodyInPhysic(body);
			else spaceAway.physic.removeBody(body);
			return enable;
		}
		
		public function callWaitBody(func: Function): void {
			function doBody(e: Event): void {
				removeEventListener(SETBODY, doBody);
				func();
			}
			if (_body) func();
			else addEventListener(SETBODY, doBody);
		}
		
		
		public function get transform(): Matrix3D {
			return getTransform();
		}
		
		public function set transform(a_transform: Matrix3D): void {
			setTransform(a_transform);
		}
		
		protected function getTransform(): Matrix3D {
			return body?body.skin.transform:null;
		}
		
		protected function setTransform(a_transform: Matrix3D): void {
			dispatchEvent(new ObjectEvent(df_chip.UPDATECHIP, this));
			if (_noActiveSphere) _noActiveSphere.transform = body.skin.transform;
		}
		
		public function get body(): RigidBody {
			return _body;
		}
		
		override public function rollY(a_roll: Number): void {
			if (_angleVelocity.y != a_roll) {
				_angleVelocity.y = a_roll;
				super.rollY(a_roll);
			}
		}
		
		override public function rollX(a_roll: Number): void {
			if (_angleVelocity.x != a_roll) {
				_angleVelocity.x = a_roll;
				super.rollX(a_roll);
			}
		}
		
		override public function rollZ(a_roll: Number): void {
			if (_angleVelocity.z != a_roll) {
				_angleVelocity.z = a_roll;
				super.rollZ(a_roll);
			}
		}
		
		override protected function update():void {
			if (_body) {
				
				_body.setAngleVelocity(_body.currentState.orientation.transformVector(_angleVelocity));
				
				var mVector: Vector3D =  _body.currentState.orientation.transformVector(new Vector3D(_slideTo, 0, _moveTo));

				_body.setLineVelocity(mVector); // Способ перемещения при помощи протягивания объекта по вектору, при таком способе не работает гравитация

/*				
				
				_body.addWorldForce(mVector, _body.currentState.position); // Способ перемещения при помощи добавления силы
				
				if (_prev) {
					var torms: Vector3D = _prev.subtract(_body.currentState.position);
					torms.scaleBy(20);
					torms = torms.add(spaceAway.physic.engine.gravity);
					_body.addWorldForce(torms, _body.currentState.position);
				}
				
				_prev = _body.currentState.position.clone();*/
				
/*				var lForce: Vector3D = _body.force.clone();
				lForce.scaleBy(-0.1);
				
				_body.addWorldForce(lForce, _body.currentState.position);*/
				
				
				if (_body.isActive) super.update();
			}
		}
		
		override public function attachToVector(v: Vector3D): void {
//			trace(Math.round(angle * 100) + ' ' + tUp);
		}
		
		override public function moveTo(a_move: Number): void {
			if (_moveTo != a_move) {
				_moveTo = a_move;
				super.moveTo(a_move);
			}
		}
		
		override public function slideTo(a_slide: Number): void {
			if (_slideTo != a_slide) {
				_slideTo = a_slide;
				super.slideTo(_slideTo);
			}
		}
		
		public function get attackableRadius(): Number {
			return (_body != null)?_body.boundingSphere:0;
		}
		
		public function checkHit(start	: Vector3D, ray		: Vector3D): Number {
			var v	: Vector3D = (new Ray()).getRayToSphereIntersection(start, ray, body.currentState.position, attackableRadius, true);
			if (v) {
				var v2: Vector3D = v.subtract(start);
				if (v2.length <= ray.length)
					return v2.length;
			}
			return -1;
		}
		
		override protected function checkHitBullet(a_bullet: IBullet): Object {
			if (body && (attackableRadius > 0) && !noActiveSphere) {
				var bullet: IAwayBullet = a_bullet  as IAwayBullet;
				var ray		: Vector3D = bullet.ray;
				if (checkHit(bullet.position.subtract(ray), ray) > -1) return {
					bullet		: bullet 
				};
				
				/*				
				var start	: Vector3D = bullet.position.subtract(ray);
				var v	: Vector3D = (new Ray()).getRayToSphereIntersection(
								start, ray, body.currentState.position, attackableRadius, true);
				
				if (v) {
					if (v.subtract(start).length <= ray.length) {
						return {
							hitVector	: v,
							bullet		: bullet
						}
					}
				}*/
			}
			return null;
		}
		
		override public function bulletHit(hitInfo: Object):void {
/*			var v: Vector3D = hitInfo.hitVector.clone();
			v.negate();
			v.scaleBy(options.maxSpeed);
			
			body.addWorldForce(v, body.currentState.position);*/
			super.bulletHit(hitInfo);
			hitInfo.bullet.hitBullet(body.skin.transform);
		}

		override protected function destruction(a_source: Object=null): void {
			this.spaceAway.dispatchEvent(new ObjectEvent(df_awaySpace.EXPLODE_SHOW, this));
			super.destruction(a_source);
		}
	}
}